/*
 * Copyright (c) 2024 OpenValley(ShenZhen) Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>

#include <los_task.h>
#include <los_arch_interrupt.h>
#include <hiview_log.h>

#include <ohos_init.h>
#include <ohos_types.h>
#include <gpio_if.h>
#include <tl_common.h>
#include <drivers.h>

#include <board_config.h>

/* File "app_config.h" should be included before B91 drivers */
#include "app_config.h"

#include <b91_irq.h>
#include <riscv_hal.h>
#include <stack/ble/ble.h>

#include "app.h"
#include "uni_ble.h"
#include <time.h>
#include "AccessoryKit.h"

#include <gpio_if.h>
#include <uart_if.h>
DevHandle *uart_handle;
#define UART0 0 // debug port
#define UART1 1
#define BAUD_115200 115200
#define BAUD_921600 921600

#define MS_MS_DELAY 1000

#define ACCEKIT_TASK_PRIORITY (OS_TASK_PRIORITY_HIGHEST)

static int is_open = 0; // UartOpen only once
void obu_uart_init(uint32_t port, uint32_t baud)
{
    /* See device/soc/telink/b91/hcs/uart/uart_config.hcs
       for hdf uart configuration */
    if(!is_open) {
        uart_handle = UartOpen(port);
        if (uart_handle == NULL) {
            printf("UartOpen %u: failed!\n", port);
        }
    }
    is_open = 1;
    UartSetBaud(uart_handle, baud);
    UartGetBaud(uart_handle, &baud);
    printf("%s: Set baudrate %u\r\n", __func__, baud);
}

uint32_t obu_uart_read(char *rxbuf, uint32_t len)
{
    uint32_t ret = UartRead(uart_handle, rxbuf, len); 
    if (ret <= 0) { // =0 no data; <0 error
        printf("UartRead %u: failed!\r\n", uart_handle);
    }
    return ret;
}

uint32_t obu_uart_write(char *txbuf, uint32_t len)
{
    uint32_t ret = UartWrite(uart_handle, txbuf, len);
    if (ret != 0) {
        printf("UartWrite %u: failed!\r\n", uart_handle);
    }
    return ret;
}

/** gpio demo */
void LedTask(void)
{
    GpioSetDir(LED_BLUE_HDF, GPIO_DIR_OUT);
    int i = 3;
    while (i--) {
        GpioWrite(LED_BLUE_HDF, GPIO_VAL_HIGH);
        LOS_Msleep(MS_MS_DELAY);

        GpioWrite(LED_BLUE_HDF, GPIO_VAL_LOW);
        LOS_Msleep(MS_MS_DELAY);
    }
}

static void AcceKitTask(void)
{
    /*
     * Enable STimer IRQ trigger if value in level register is below tick.
     * Without this line STimer interrupt will be missed if interrupts were disabled when
     * COUNT register reached value of LEVEL register.
     */
    reg_system_irq_mask |= FLD_SYSTEM_TRIG_PAST_EN;

    HILOG_INFO(HILOG_MODULE_APP, "%s:%d", __func__, __LINE__);
    int count = 0;
    char notify_data[25] = {0};
    char get_data_buff[30] = {0};
    while (1) {
        AcceKitMainLoop(); 
        LOS_TaskDelay(10);
        if(AcceKitStatus()==ACCEKIT_CONNECTED)
        {
            LOS_TaskDelay(5);
        }
        if(AcceKitStatus()==ACCEKIT_RECEIVE_DATA)
        {
            if(AcceKitGetData(get_data_buff))
            {
                /**Initialize UART after connecting the device or use UART in other tasks.
                 * see vendor/telink/accessory_kit_demo/accessory_kit_obu/uart_rw_obu.c
                 */
                obu_uart_init(UART1, BAUD_921600);
                printf("get_data_buff=%s\r\n", get_data_buff);
                sprintf(notify_data, "%s%d", get_data_buff, count);
                count ++;
                AcceKitSendData(notify_data, sizeof(notify_data));
                obu_uart_write(notify_data, sizeof(notify_data));
            }
        }
    }
}

void AcceKitTaskSampleInit(void)
{
    /*Initialize AcceKit before create task*/
    AcceKitInit();

    /*Change OBU config parameter after AcceKitInit */
    const char tmp_tbl_scanRsp [] = {
    0x08, 0x09, '1', 'B', 'U', 'D', 'e', 'm', 'o', 
    };
    const unsigned char temp_tbl_advData[] = {
    0x05, 0x09, '2', 'O', 'B', 'U',
    0x02, 0x01, 0x05,                        // BLE limited discoverable mode and BR/EDR not supported
    0x03, 0x19, 0x80, 0x01,                  // 384, Generic Remote Control, Generic category
    0x05, 0x02, 0x12, 0x18, 0x0F, 0x18,      // incomplete list of service class UUIDs (0x1812, 0x180F)
    };
    uni_ble_ll_setAdvData((u8 *)temp_tbl_advData, sizeof(temp_tbl_advData));
    uni_ble_ll_setScanRspData((u8 *)tmp_tbl_scanRsp, sizeof(tmp_tbl_scanRsp));

    /*creat demo task */
    UINT32 ret;
    UINT32 taskId = 0;
    TSK_INIT_PARAM_S taskParam = {0};
    taskParam.pfnTaskEntry = (TSK_ENTRY_FUNC)AcceKitTask;
    taskParam.uwArg = 0;
    taskParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE+1024;
    taskParam.pcName = "AcceKitTask";
    taskParam.usTaskPrio = ACCEKIT_TASK_PRIORITY;
    ret = LOS_TaskCreate(&taskId, &taskParam);
    if (ret != LOS_OK) {
        HILOG_ERROR(HILOG_MODULE_APP, "ret of LOS_TaskCreate(AcceKitTask) = %#x", ret);
    }
    
    /*Initialize AcceKitIrq after create task*/
    AcceKitIrqInit();

}

SYS_RUN(AcceKitTaskSampleInit);
